import axios from 'axios'

// 导入更新的token接口函数
import { updateTokenAPI } from '@/api/user'

// 导入 store 模块
import store from '@/store/index'

// 导入router
import router from '@/router/index'

// 从vant组件导入轻提示
import { Toast } from 'vant'

// 新建一个新的axios实例
const request = axios.create({
  baseURL: 'http://toutiao.itheima.net', // 基地址
  timeout: 5000 // 请求超过5秒钟还没有响应视为失败
})

// 请求拦截器
// config就是请求对象，里面包含了此次请求的所用的信息
request.interceptors.request.use((config) => {
  // 在发送请求之前做什么
  // 统一携带 token 给后台
  const { token } = store.state.user
  // 如果 token 有值，则通过 Authorization 字段传递给后台
  if (token) {
    // 给请求头添加 Authorization 属性，把登陆成功的 token 发给服务器
    config.headers.Authorization = `Bearer ${token}`
  }
  // 必须要返回 config ，不然请求会失败
  return config
}, (err) => {
  // 对请求错误做些什么
  return Promise.reject(err)
})

// 响应拦截器
// 服务器在相应给接口函数之前必须经过这一道关卡，可以在响应拦截器中对响应做公共处理
request.interceptors.response.use((response) => {
  // 成功的回调(当http状态码以2或3开头)都会走这里
  // 对响应数据做点什么
  // 响应成功了，直接把data数据返回给调用接口函数的地方
  // 这样接口函数拿到的数据可以少写一层.data，这个操作可以称为剥离响应无效数据
  return response.data
}, async (error) => {
  // todo：token过期处理
  if (error.response.status === 401) {
    try {
      // 情况1：token过期了,但refreshToken未过期
      // 调用更新token的接口
      const resp = await updateTokenAPI()
      // 用新的token去更新旧的token（在vuex中更新，调用setToken函数）
      store.commit('user/setToken', resp.data.data.token)
      // 用得到的新的token继续之前未遂的请求
      // 继续调用request发请求，error.config获取的请求失败接口的所有请求信息
      return request(error.config)
      // axios写法
      // return axios({
      //   ...error.config,
      //   url: `http://toutiao.itheima.net${error.comfig.url}`,
      //   headers: {
      //     Authorization: `Bearer ${resp.data.data.token}`
      //   }
      // })
    } catch (e) {
      // 情况2：两个都过期了
      // 代码走到这了，说明 refreshToken 也过期了
      if (e.response.data.message === 'refresh_token失效') {
        // 给个登陆过期的提示
        Toast('登陆已过期，请重新登陆')
        // 清空vuex中的token和refreshToken
        store.dispatch('user/logoutAction')
        // 跳转至登录页，并携带回跳地址
        // $route：当前激活的路由对象(在组件中使用)
        // router.currentRoute：当前激活的路由对象(在js页面中使用)
        router.push(`/login?redirectUrl=${router.currentRoute}`)
      }
    }
  }
  // 请求失败的回调(当http状态码以4或5开头)走这里
  // 对响应错误做点什么
  return Promise.reject(error)
})

// 导出自定义函数
export default request

// token过期解决：
// 续签的思路：
// 前提：有很多接口发给服务器的时候（请求拦截器中统一携带）需要携带token
// 但如果发给服务器是过期的token，此次请求会失败，服务器响应401状态码
// 1.当token过期了，在响应拦截器中统一处理
// 2.通过refreshToken去获取一个新的token（refreshToken有效期比token长）
// 3.用得到的新token，继续之前未遂的请求
